<!DOCTYPE html>

<html>
<head>
<title>Building Admin - Worker - QOR5 Document</title>

<meta name='description'>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<base href='/docs/'>

<link href='index.css' rel='stylesheet' type='text/css'>

<script type='text/javascript' defer src='index.js'></script>
</head>

<body>
<div id='app' v-cloak>
<div v-init-context:vars='{hideAside: false}' class='flex h-screen'>
<div class='flex-1 flex flex-col overflow-hidden'>
<div class='flex h-full'>
<aside v-show='!vars.hideAside' id='menuScroller' class='flex flex-col w-80 h-full bg-gray-50 border-r border-gray-200 overflow-y-auto'>
<div class='h-12'><search></search></div>

<ul class='px-0 py-3 mx-0 text-base font-normal list-none text-gray-700'>
<li class='m-0'>
<a href='index.html' id='index.html' onclick='window.storeMenuState("index.html")' class='inline-block px-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Introduction</a>
</li>

<li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Getting Started</li>

<li class='m-0'>
<a href='getting-started/one-minute-quick-start.html' id='getting-started/one-minute-quick-start.html' onclick='window.storeMenuState("getting-started/one-minute-quick-start.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>1 Minute Quick Start</a>
</li>

<li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Building Admin</li>

<li class='m-0'>
<a href='basics/presets-instant-crud.html' id='basics/presets-instant-crud.html' onclick='window.storeMenuState("basics/presets-instant-crud.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>presets, Instant CRUD</a>
</li>

<li class='m-0'>
<a href='basics/listing.html' id='basics/listing.html' onclick='window.storeMenuState("basics/listing.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Listing</a>
</li>

<li class='m-0'>
<a href='basics/listing-customizations.html' id='basics/listing-customizations.html' onclick='window.storeMenuState("basics/listing-customizations.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Listing Customizations</a>
</li>

<li class='m-0'>
<a href='basics/filter.html' id='basics/filter.html' onclick='window.storeMenuState("basics/filter.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Filters</a>
</li>

<li class='m-0'>
<a href='presets-guide/editing-customizations.html' id='presets-guide/editing-customizations.html' onclick='window.storeMenuState("presets-guide/editing-customizations.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Editing</a>
</li>

<li class='m-0'>
<a href='basics/brand.html' id='basics/brand.html' onclick='window.storeMenuState("basics/brand.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Brand</a>
</li>

<li class='m-0'>
<a href='basics/menu.html' id='basics/menu.html' onclick='window.storeMenuState("basics/menu.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Menu</a>
</li>

<li class='m-0'>
<a href='presets-guide/detail-page-for-complex-object.html' id='presets-guide/detail-page-for-complex-object.html' onclick='window.storeMenuState("presets-guide/detail-page-for-complex-object.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Detailing</a>
</li>

<li class='m-0'>
<a href='basics/layout.html' id='basics/layout.html' onclick='window.storeMenuState("basics/layout.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Layout</a>
</li>

<li class='m-0'>
<a href='basics/login.html' id='basics/login.html' onclick='window.storeMenuState("basics/login.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Login</a>
</li>

<li class='m-0'>
<a href='presets-guide/permissions.html' id='presets-guide/permissions.html' onclick='window.storeMenuState("presets-guide/permissions.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Permissions</a>
</li>

<li class='m-0'>
<a href='presets-guide/role.html' id='presets-guide/role.html' onclick='window.storeMenuState("presets-guide/role.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Role</a>
</li>

<li class='m-0'>
<a href='basics/shortcut.html' id='basics/shortcut.html' onclick='window.storeMenuState("basics/shortcut.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Keyboard Shortcut</a>
</li>

<li class='m-0'>
<a href='basics/confirm-dialog.html' id='basics/confirm-dialog.html' onclick='window.storeMenuState("basics/confirm-dialog.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Confirm Dialog</a>
</li>

<li class='m-0'>
<a href='slug.html' id='slug.html' onclick='window.storeMenuState("slug.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Slug</a>
</li>

<li class='m-0'>
<a href='seo.html' id='seo.html' onclick='window.storeMenuState("seo.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>SEO</a>
</li>

<li class='m-0'>
<a href='activity-log.html' id='activity-log.html' onclick='window.storeMenuState("activity-log.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Activity Log</a>
</li>

<li class='m-0'>
<a href='basics/worker.html' id='basics/worker.html' onclick='window.storeMenuState("basics/worker.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-blue-500'>Worker</a>
</li>

<li class='m-0'>
<a href='basics/publish.html' id='basics/publish.html' onclick='window.storeMenuState("basics/publish.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Publish</a>
</li>

<li class='m-0'>
<a href='basics/i18n.html' id='basics/i18n.html' onclick='window.storeMenuState("basics/i18n.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Internationalization</a>
</li>

<li class='m-0'>
<a href='basics/l10n.html' id='basics/l10n.html' onclick='window.storeMenuState("basics/l10n.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Localization</a>
</li>

<li class='m-0'>
<a href='basics/redirection.html' id='basics/redirection.html' onclick='window.storeMenuState("basics/redirection.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Redirection</a>
</li>

<li class='m-0'>
<a href='basics/custom-page.html' id='basics/custom-page.html' onclick='window.storeMenuState("basics/custom-page.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Custom Pages</a>
</li>

<li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Web Application</li>

<li class='m-0'>
<a href='advanced-functions/the-go-html-builder.html' id='advanced-functions/the-go-html-builder.html' onclick='window.storeMenuState("advanced-functions/the-go-html-builder.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>The Go HTML builder</a>
</li>

<li class='m-0'>
<a href='basics/page-func-and-event-func.html' id='basics/page-func-and-event-func.html' onclick='window.storeMenuState("basics/page-func-and-event-func.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Page Func and Event Func</a>
</li>

<li class='m-0'>
<a href='basics/layout-function-and-page-injector.html' id='basics/layout-function-and-page-injector.html' onclick='window.storeMenuState("basics/layout-function-and-page-injector.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Layout Function and Page Injector</a>
</li>

<li class='m-0'>
<a href='vuetify-components/lazy-portals.html' id='vuetify-components/lazy-portals.html' onclick='window.storeMenuState("vuetify-components/lazy-portals.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Lazy Portals</a>
</li>

<li class='m-0'>
<a href='basics/switch-pages-with-push-state.html' id='basics/switch-pages-with-push-state.html' onclick='window.storeMenuState("basics/switch-pages-with-push-state.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Switch Pages with Push State</a>
</li>

<li class='m-0'>
<a href='basics/reload-page-with-a-flash.html' id='basics/reload-page-with-a-flash.html' onclick='window.storeMenuState("basics/reload-page-with-a-flash.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Reload Page with a Flash</a>
</li>

<li class='m-0'>
<a href='basics/partial-refresh-with-portal.html' id='basics/partial-refresh-with-portal.html' onclick='window.storeMenuState("basics/partial-refresh-with-portal.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Partial Refresh with Portal</a>
</li>

<li class='m-0'>
<a href='basics/manipulate-page-url-in-event-func.html' id='basics/manipulate-page-url-in-event-func.html' onclick='window.storeMenuState("basics/manipulate-page-url-in-event-func.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Manipulate Page URL in Event Func</a>
</li>

<li class='m-0'>
<a href='basics/summary-of-event-response.html' id='basics/summary-of-event-response.html' onclick='window.storeMenuState("basics/summary-of-event-response.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Summary of Event Response</a>
</li>

<li class='m-0'>
<a href='basics/web-scope.html' id='basics/web-scope.html' onclick='window.storeMenuState("basics/web-scope.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>web.Scope</a>
</li>

<li class='m-0'>
<a href='basics/event-handling.html' id='basics/event-handling.html' onclick='window.storeMenuState("basics/event-handling.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Event Handling</a>
</li>

<li class='m-0'>
<a href='basics/form-handling.html' id='basics/form-handling.html' onclick='window.storeMenuState("basics/form-handling.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Form Handling</a>
</li>

<li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>UI Components</li>

<li class='m-0'>
<a href='vuetify-components/basic-inputs.html' id='vuetify-components/basic-inputs.html' onclick='window.storeMenuState("vuetify-components/basic-inputs.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Basic Inputs</a>
</li>

<li class='m-0'>
<a href='vuetify-components/a-taste-of-using-vuetify-in-go.html' id='vuetify-components/a-taste-of-using-vuetify-in-go.html' onclick='window.storeMenuState("vuetify-components/a-taste-of-using-vuetify-in-go.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>A Taste of using Vuetify in Go</a>
</li>

<li class='m-0'>
<a href='vuetify-components/linkage-select.html' id='vuetify-components/linkage-select.html' onclick='window.storeMenuState("vuetify-components/linkage-select.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Linkage Select</a>
</li>

<li class='m-0'>
<a href='components-guide/composite-new-component-with-go.html' id='components-guide/composite-new-component-with-go.html' onclick='window.storeMenuState("components-guide/composite-new-component-with-go.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Composite new Component With Go</a>
</li>

<li class='m-0'>
<a href='components-guide/integrate-a-heavy-vue-component.html' id='components-guide/integrate-a-heavy-vue-component.html' onclick='window.storeMenuState("components-guide/integrate-a-heavy-vue-component.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Integrate a heavy Vue Component</a>
</li>

<li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Appendix</li>

<li class='m-0'>
<a href='appendix/all-demo-examples.html' id='appendix/all-demo-examples.html' onclick='window.storeMenuState("appendix/all-demo-examples.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>All Demo Examples</a>
</li>
</ul>
</aside>

<main class='flex flex-col w-full bg-white overflow-x-hidden overflow-y-auto'>
<div id='docContentBox' class='flex flex-row w-full'>
<div class='flex flex-grow flex-col w-2/3'>
<div class='flex flex-row'>
<button @click='vars.hideAside = !vars.hideAside' class='w-12 h-12 p-4'>
<div class='w-4 h-4 fill-current text-gray-300'>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 2 12 L 2 11 L 14 11 L 14 12 Z M 2 8.5 L 2 7.5 L 14 7.5 L 14 8.5 Z M 2 5 L 2 4 L 14 4 L 14 5 Z M 2 5 "/>
</g>
</svg>
</div>
</button>
</div>

<div id='docMainBox' class='px-16 pb-12 pt-4 overflow-auto'>
<h1 class='mb-8'>Worker</h1>

<div class='border-t'><p>Worker runs a single Job in the background, it can do so immediately or at a scheduled time.<br>
Once registered with QOR Admin, Worker will provide a Workers section in the navigation tree, containing pages for listing and managing the following aspects of Workers:</p>

<ul>
<li>All Jobs.</li>
<li>Running: Jobs that are currently running.</li>
<li>Scheduled: Jobs which have been scheduled to run at a time in the future.</li>
<li>Done: finished Jobs.</li>
<li>Errors: any errors output from any Workers that have been run.</li>
</ul>
<h2><a name="note" class="anchor" href="#note" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>
Note</h2>

<ul>
<li>The default que GoQueQueue(<a href="https://github.com/tnclong/go-que" rel="nofollow">https://github.com/tnclong/go-que</a>) only supports postgres for now.</li>
<li>To make a job abortable, you need to check <code>ctx.Done()</code> channel in job handler and stop the handler func.
<br></li>
</ul>
<h2><a name="example" class="anchor" href="#example" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>Example</h2>

<highlightjs :language='"go"' :code='"import (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/qor5/admin/v3/presets\"\n\t\"github.com/qor5/admin/v3/worker\"\n)\n\nfunc MountWorker(b *presets.Builder) {\n\tDB := ExampleDB()\n\n\twb := worker.New(DB)\n\twb.Install(b)\n\tdefer wb.Listen()\n\n\taddJobs(wb)\n}\n\nfunc addJobs(w *worker.Builder) {\n\tw.NewJob(\"noArgJob\").\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjob.AddLog(\"hoho1\")\n\t\t\tjob.AddLog(\"hoho2\")\n\t\t\tjob.AddLog(\"hoho3\")\n\t\t\treturn nil\n\t\t})\n\n\ttype ArgJobResource struct {\n\t\tF1 string\n\t\tF2 int\n\t\tF3 bool\n\t}\n\targJb := w.NewJob(\"argJob\").\n\t\tResource(\u0026ArgJobResource{}).\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjobInfo, _ := job.GetJobInfo()\n\t\t\tjob.AddLog(fmt.Sprintf(\"Argument %#+v\", jobInfo.Argument))\n\t\t\treturn nil\n\t\t})\n\t// you can to customize the resource Editing via GetResourceBuilder()\n\targJb.GetResourceBuilder().Editing()\n\n\tw.NewJob(\"progressTextJob\").\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjob.AddLog(\"hoho1\")\n\t\t\tjob.AddLog(\"hoho2\")\n\t\t\tjob.AddLog(\"hoho3\")\n\t\t\tjob.SetProgressText(`\u003ca href=\"https://www.google.com\"\u003eDownload users\u003c/a\u003e`)\n\t\t\treturn nil\n\t\t})\n\n\t// check ctx.Done() to stop the handler\n\tw.NewJob(\"longRunningJob\").\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tfor i := 1; i \u003c= 5; i++ {\n\t\t\t\tselect {\n\t\t\t\tcase \u003c-ctx.Done():\n\t\t\t\t\tjob.AddLog(\"job aborted\")\n\t\t\t\t\treturn nil\n\t\t\t\tdefault:\n\t\t\t\t\tjob.AddLog(fmt.Sprintf(\"%v\", i))\n\t\t\t\t\tjob.SetProgress(uint(i * 20))\n\t\t\t\t\ttime.Sleep(time.Second)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\n\t// insert worker.Schedule to resource to make a job schedulable\n\ttype ScheduleJobResource struct {\n\t\tF1 string\n\t\tworker.Schedule\n\t}\n\tw.NewJob(\"scheduleJob\").\n\t\tResource(\u0026ScheduleJobResource{}).\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjobInfo, _ := job.GetJobInfo()\n\t\t\tjob.AddLog(fmt.Sprintf(\"%#+v\", jobInfo.Argument))\n\t\t\treturn nil\n\t\t})\n\n\tw.NewJob(\"errorJob\").\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjob.AddLog(\"=====perform error job\")\n\t\t\treturn errors.New(\"imError\")\n\t\t})\n\n\tw.NewJob(\"panicJob\").\n\t\tHandler(func(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjob.AddLog(\"=====perform panic job\")\n\t\t\tpanic(\"letsPanic\")\n\t\t})\n}\n"'></highlightjs>

<div>
<div class='demo'>
<a href='/examples/worker-example/workers' target='_blank'>Check the demo</a>
 | 
<a href='https://github.com/qor5/admin/tree/main/docs/docsrc/examples/examples_admin/worker.go#L3-L100' target='_blank'>Source on GitHub</a>
</div>
</div>
<h2><a name="action-worker" class="anchor" href="#action-worker" rel="nofollow" aria-hidden="true"><span class="octicon octicon-link"></span></a>Action Worker</h2>

<p>Action Worker is used to visualize the progress of long-running actions.</p>

<highlightjs :language='"go"' :code='"import (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/qor5/admin/v3/presets\"\n\t\"github.com/qor5/admin/v3/worker\"\n\t\"github.com/qor5/web/v3\"\n\t\"github.com/qor5/x/v3/ui/vuetify\"\n\th \"github.com/theplant/htmlgo\"\n\t\"gorm.io/gorm\"\n)\n\ntype ExampleResource struct {\n\tgorm.Model\n\tName string\n}\n\nfunc MountActionWorker(b *presets.Builder) {\n\tDB := ExampleDB()\n\tmb := b.Model(\u0026ExampleResource{})\n\tmb.Listing().ActionsAsMenu(true)\n\n\twb := worker.New(DB)\n\twb.Install(b)\n\tdefer wb.Listen()\n\n\taddActionJobs(mb, wb)\n}\n\nfunc addActionJobs(mb *presets.ModelBuilder, wb *worker.Builder) {\n\tlb := mb.Listing()\n\n\tnoParametersJob := wb.ActionJob(\n\t\t\"No parameters\",\n\t\tmb,\n\t\tfunc(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tfor i := 1; i \u003c= 10; i++ {\n\t\t\t\tselect {\n\t\t\t\tcase \u003c-ctx.Done():\n\t\t\t\t\tjob.AddLog(\"job aborted\")\n\t\t\t\t\treturn nil\n\t\t\t\tdefault:\n\t\t\t\t\tjob.SetProgress(uint(i * 10))\n\t\t\t\t\ttime.Sleep(time.Second)\n\t\t\t\t}\n\t\t\t}\n\t\t\tjob.SetProgressText(`\u003ca href=\"https://qor5-test.s3.ap-northeast-1.amazonaws.com/system/media_libraries/37/file.@qor_preview.png\"\u003ePlease download this file\u003c/a\u003e`)\n\t\t\treturn nil\n\t\t},\n\t).Description(\"This test demo is used to show that an no parameter job can be executed\")\n\n\tparametersBoxJob := wb.ActionJob(\n\t\t\"Parameter input box\",\n\t\tmb,\n\t\tfunc(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tfor i := 1; i \u003c= 10; i++ {\n\t\t\t\tselect {\n\t\t\t\tcase \u003c-ctx.Done():\n\t\t\t\t\tjob.AddLog(\"job aborted\")\n\t\t\t\t\treturn nil\n\t\t\t\tdefault:\n\t\t\t\t\tjob.SetProgress(uint(i * 10))\n\t\t\t\t\ttime.Sleep(time.Second)\n\t\t\t\t}\n\t\t\t}\n\t\t\tjob.SetProgressText(`\u003ca href=\"https://qor5-test.s3.ap-northeast-1.amazonaws.com/system/media_libraries/37/file.@qor_preview.png\"\u003ePlease download this file\u003c/a\u003e`)\n\t\t\treturn nil\n\t\t},\n\t).Description(\"This test demo is used to show that an input box when there are parameters\").\n\t\tParams(\u0026struct{ Name string }{})\n\n\tdisplayLogJob := wb.ActionJob(\n\t\t\"Display log\",\n\t\tmb,\n\t\tfunc(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tfor i := 1; i \u003c= 10; i++ {\n\t\t\t\tselect {\n\t\t\t\tcase \u003c-ctx.Done():\n\t\t\t\t\tjob.AddLog(\"job aborted\")\n\t\t\t\t\treturn nil\n\t\t\t\tdefault:\n\t\t\t\t\tjob.SetProgress(uint(i * 10))\n\t\t\t\t\tjob.AddLog(fmt.Sprintf(\"%v\", i))\n\t\t\t\t\ttime.Sleep(time.Second)\n\t\t\t\t}\n\t\t\t}\n\t\t\tjob.SetProgressText(`\u003ca href=\"https://qor5-test.s3.ap-northeast-1.amazonaws.com/system/media_libraries/37/file.@qor_preview.png\"\u003ePlease download this file\u003c/a\u003e`)\n\t\t\treturn nil\n\t\t},\n\t).Description(\"This test demo is used to show the log section of this job\").\n\t\tParams(\u0026struct{ Name string }{}).\n\t\tDisplayLog(true).\n\t\tProgressingInterval(4000)\n\n\tgetArgsJob := wb.ActionJob(\n\t\t\"Get Args\",\n\t\tmb,\n\t\tfunc(ctx context.Context, job worker.QorJobInterface) error {\n\t\t\tjobInfo, err := job.GetJobInfo()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tjob.AddLog(fmt.Sprintf(\"Action Params Name is  %#+v\", jobInfo.Argument.(*struct{ Name string }).Name))\n\t\t\tjob.AddLog(fmt.Sprintf(\"Origina Context AuthInfo is  %#+v\", jobInfo.Context[\"AuthInfo\"]))\n\t\t\tjob.AddLog(fmt.Sprintf(\"Origina Context URL is  %#+v\", jobInfo.Context[\"URL\"]))\n\n\t\t\tfor i := 1; i \u003c= 10; i++ {\n\t\t\t\tselect {\n\t\t\t\tcase \u003c-ctx.Done():\n\t\t\t\t\treturn nil\n\t\t\t\tdefault:\n\t\t\t\t\tjob.SetProgress(uint(i * 10))\n\t\t\t\t\ttime.Sleep(time.Second)\n\t\t\t\t}\n\t\t\t}\n\t\t\tjob.SetProgressText(`\u003ca href=\"https://qor5-test.s3.ap-northeast-1.amazonaws.com/system/media_libraries/37/file.@qor_preview.png\"\u003ePlease download this file\u003c/a\u003e`)\n\t\t\treturn nil\n\t\t},\n\t).Description(\"This test demo is used to show how to get the action&#39;s arguments and original page context\").\n\t\tParams(\u0026struct{ Name string }{}).\n\t\tDisplayLog(true).\n\t\tContextHandler(func(ctx *web.EventContext) map[string]interface{} {\n\t\t\tauth, err := ctx.R.Cookie(\"auth\")\n\t\t\tif err == nil {\n\t\t\t\treturn map[string]interface{}{\"AuthInfo\": auth.Value}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\n\tlb.Action(\"Action Job - No parameters\").\n\t\tButtonCompFunc(\n\t\t\tfunc(ctx *web.EventContext) h.HTMLComponent {\n\t\t\t\treturn vuetify.VBtn(\"Action Job - No parameters\").Color(\"secondary\").Class(\"ml-2\").\n\t\t\t\t\tAttr(\"@click\", noParametersJob.URL())\n\t\t\t})\n\n\tlb.Action(\"Action Job - Parameter input box\").\n\t\tButtonCompFunc(\n\t\t\tfunc(ctx *web.EventContext) h.HTMLComponent {\n\t\t\t\treturn vuetify.VBtn(\"Action Job - Parameter input box\").Color(\"secondary\").Class(\"ml-2\").\n\t\t\t\t\tAttr(\"@click\", parametersBoxJob.URL())\n\t\t\t})\n\tlb.Action(\"Action Job - Display log\").\n\t\tButtonCompFunc(\n\t\t\tfunc(ctx *web.EventContext) h.HTMLComponent {\n\t\t\t\treturn vuetify.VBtn(\"Action Job - Display log\").Color(\"secondary\").Class(\"ml-2\").\n\t\t\t\t\tAttr(\"@click\", displayLogJob.URL())\n\t\t\t})\n\n\tlb.Action(\"Action Job - Get Args\").\n\t\tButtonCompFunc(\n\t\t\tfunc(ctx *web.EventContext) h.HTMLComponent {\n\t\t\t\treturn vuetify.VBtn(\"Action Job - Get Args\").Color(\"secondary\").Class(\"ml-2\").\n\t\t\t\t\tAttr(\"@click\", getArgsJob.URL())\n\t\t\t})\n}\n"'></highlightjs>

<div>
<div class='demo'>
<a href='/examples/action-worker-example/example-resources' target='_blank'>Check the demo</a>
 | 
<a href='https://github.com/qor5/admin/tree/main/docs/docsrc/examples/examples_admin/action_worker.go#L3-L163' target='_blank'>Source on GitHub</a>
</div>
</div>
</div>
</div>
</div>

<div class='font-medium text-base hidden xl:block text-gray-600 pt-4'>
<div class='sticky top-4 w-52'>On This Page<toc></toc></div>
</div>
</div>
<search-result></search-result></main>
</div>
</div>
</div>
</div>
</body>
</html>
